using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Windows.Forms;

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
using System.Threading;
using System.ComponentModel;
using EntLibContrib.PolicyInjection.CallHandlers;

namespace EntLibContrib.PolicyInjection.Tests
{
    [TestClass]
    public class SynchronizedCallHandlerFixture
    {
        [TestMethod, DeploymentItem("SynchronizedCallHandler.config")]
        public void Target_With_Configuration_Implements_ISynchronizeInvoke()
        {
            IConfigurationSource configurationSource = new FileConfigurationSource("SynchronizedCallHandler.config");

            SynchronizedFoo foo = Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.Create<SynchronizedFoo>(configurationSource);
            foo.InvokeRequired = true;
            foo.Do();
        }

        [TestMethod]
        public void Target_With_Attributes_Implements_ISynchronizeInvoke()
        {
            SynchronizedFooWithAttributes foo = Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.Create<SynchronizedFooWithAttributes>();
            foo.InvokeRequired = true;
            foo.Do();
        }
    }

    public class SynchronizedFoo : MarshalByRefObject, ISynchronizeInvoke
    {
        private bool invokeRequired = false;
        private bool invokedSynchronously = false;

        public void Do()
        {
            Assert.AreEqual(invokeRequired, invokedSynchronously);
        }

        #region ISynchronizeInvoke Members

        public IAsyncResult BeginInvoke(Delegate method, object[] args)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public object EndInvoke(IAsyncResult result)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public object Invoke(Delegate method, object[] args)
        {
            if (InvokeRequired)
            {
                invokedSynchronously = true;
            }

            return method.DynamicInvoke(args);
        }

        public bool InvokeRequired
        {
            get { return invokeRequired; }
            set { invokeRequired = value; }
        }

        #endregion
    }

    [SynchronizedCallHandler]
    public class SynchronizedFooWithAttributes : MarshalByRefObject, ISynchronizeInvoke
    {
        private bool invokeRequired = false;
        private bool invokedSynchronously = false;

        public void Do()
        {
            Assert.AreEqual(invokeRequired, invokedSynchronously);
        }

        #region ISynchronizeInvoke Members

        public IAsyncResult BeginInvoke(Delegate method, object[] args)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public object EndInvoke(IAsyncResult result)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public object Invoke(Delegate method, object[] args)
        {
            if (InvokeRequired)
            {
                invokedSynchronously = true;
            }

            return method.DynamicInvoke(args);
        }

        public bool InvokeRequired
        {
            get { return invokeRequired; }
            set { invokeRequired = value; }
        }

        #endregion
    }
}

